package com.zjhome.cloudnote.filter;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.ibatis.javassist.bytecode.ByteArray;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.io.ByteStreams;
import com.zjhome.cloudnote.constant.ConstantKey;
import com.zjhome.cloudnote.domain.UserInfo;
import com.zjhome.cloudnote.param.LoginParam;
import com.zjhome.cloudnote.util.SerializeUtil;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Setter;

/**
 * 验证用户名密码后，生成一个token，并将token返回给客户端
 * 该类继承自UsernamePasswordAuthenticationFilter，重写了其中的2个方法
 * attemptAuthentication： 接受并解析用户凭证
 * successfulAuthentication：用户登陆成功后，这个方法会被调用，我们在这个方法里生成token
 * 
 * @author 0283000121
 *
 */
@AllArgsConstructor
public class JWTLoginFilter extends UsernamePasswordAuthenticationFilter {
	
	private AuthenticationManager 	authenticationManager;
	
	/**
	 * 接收并解析用户凭证
	 */
	@Override
	public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
			throws AuthenticationException {
		// 
		try {
			LoginParam loginParam = null;
			String header = request.getHeader("Content-Type");

			if (header.indexOf("x-www-form-urlencoded") != -1) {				
//				loginParam = new LoginParam(
//					request.getParameter("username"), 
//					request.getParameter("password")
//				);
				loginParam = new LoginParam();
				loginParam.setUsername(request.getParameter("username"));
				loginParam.setPassword(request.getParameter("password"));					
			}
			else {
				// json 方式获取
				loginParam = new ObjectMapper().readValue(request.getInputStream(), LoginParam.class);
			}			
			
			return authenticationManager.authenticate(
				new UsernamePasswordAuthenticationToken(
						loginParam.getUsername(),
						loginParam.getPassword(),
						new ArrayList<>()
				)
			);
			
		} catch (IOException e) {
			throw new RuntimeException(e);
		}		
	}

	/**
	 * 用户成功登陆后，这个方法会被调用，我们在这个方法里生成token
	 */
	@Override
	protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
			Authentication authResult) throws IOException, ServletException {
		// builder the token 
		String token = null;
		
		try {
			Collection<? extends GrantedAuthority> authorities = authResult.getAuthorities();
			// 定义存放角色集合的对象
			List roleList = new ArrayList<>();
			for (GrantedAuthority grantedAuthority : authorities) {
				roleList.add(grantedAuthority.getAuthority());
			}
			Calendar calendar = Calendar.getInstance();
			Date now = calendar.getTime();
			// 设置签发时间
			calendar.setTime(new Date());
			// 设置过期时间
			calendar.add(Calendar.HOUR, 1); 	// 10 小时
			Date time = calendar.getTime();
			
//			String subject = authResult.getName() + "-" + roleList;
//			String subject = SerializeUtil.serialize(authResult);
//			String subject = authResult.getName();
			
			Claims claims = Jwts.claims();			
			claims.put("userid", authResult.getPrincipal());
			claims.put("roles", roleList);				
						
			token = Jwts.builder()			
//				.setSubject(subject)
				.setClaims(claims)
				.setIssuedAt(now)		// 签发时间
				.setExpiration(time)	// 过期时间
				.signWith(SignatureAlgorithm.HS512, ConstantKey.SIGNING_KEY)	// 这里可以自定义算法
				.compact();
			// 登陆成功后，返回token到header里面
//			response.addHeader("Authorization", "Bearer " + token);
			response.addHeader("Authorization", token);
						
			// 将实体转换为json
			Map<String, Object> params = new HashMap<String, Object>();			
			params.put("token", token);
			
//			Object json = JSON.toJSON(params);
			String jsonString = JSONObject.toJSONString(params);
			
			response.setCharacterEncoding("UTF-8");
			response.setContentType("application/json;charset=utf-8");
			PrintWriter writer = response.getWriter();
			writer.append(jsonString);
			
		} catch (Exception e) {
			e.printStackTrace();
		}		
	}
}
